package com.bl.mappio.proxy.server;


import com.bl.common.entity.Message;
import com.bl.common.entity.ProxyConfig;
import com.bl.mappio.proxy.server.entity.ClientProxyConfig;
import com.bl.mappio.transmit.TransmitServer;
import com.bl.nio.common.entity.SocketClient;
import com.bl.nio.common.handler.IEventHandler;
import com.bl.nio.common.pack.EventPack;
import com.bl.nio.common.pack.HeartbeatPack;

import java.io.IOException;
import java.net.BindException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 作者 : blownsow
 * @version 版本: 1.0
 * @date 创建时间 : 2019/12/7 15:27
 * @describe 类描述:
 */
public class ProxyServerClientHandler implements IEventHandler {
    //clientId
    private Map<String,List<ProxyConfig>> clientMaps = new HashMap<>();

    private final Proxy proxy = new Proxy();
    @Override
    public void onConnect(SocketClient client) {
        System.out.println("onConnect,"+client);
    }

    @Override
    public synchronized void onDisConnect(SocketClient client) {
        System.out.println("onDisConnect,"+client);
        //把这个客户端关联的端口删除
        proxy.close(client);
    }


    @Override
    public void onHeartbeatPack(SocketClient client, HeartbeatPack heartbeatPack) {
//        System.out.println("onHeartbeatPack");
    }


    @Override
    public void onMessage(SocketClient client, Object message) {
//        System.out.println("onMessage,"+message);
    }


    @Override
    public void onEventPack(SocketClient client, EventPack pack) {
        System.out.println("onEventPack,"+pack);
        if (pack.getName().equals("init")){
            onConfig(client,pack);
        }
        if (pack.getName().equals("proxy")){
            onProxy(client,pack);
        }
    }
    private void onProxy(SocketClient client, EventPack pack){
        Message message = (Message) pack.getData();
        ProxyServer.cacheProxyMessages.put(pack.getUuid(),message);
        System.out.println("收到代理内容，"+message);
    }

    private synchronized void onConfig(SocketClient client, EventPack pack){
        Map<String,Object> map = (Map<String, Object>) pack.getData();
        List<ProxyConfig> proxyConfigs = (List<ProxyConfig>)map.get("proxyConfigs");
        String token = map.get("token").toString();
        client.setToken(token);

        System.out.println("收到配置,"+proxyConfigs);

        proxy.add(client,proxyConfigs);

        clientMaps.put(client.getClientId(),proxyConfigs);
        System.out.println("配置成功");
    }

    class Proxy{
        private final Map<String, TransmitServer> transmitServerMap = new ConcurrentHashMap<>();

        public void close(SocketClient client){
            if (clientMaps.containsKey(client.getClientId())){
                List<ProxyConfig> proxyConfigs = clientMaps.get(client.getClientId());
                for (ProxyConfig proxyConfig : proxyConfigs) {

                    if (ProxyServer.proxyMap.containsKey(proxyConfig.getRemote())){
                        List<ClientProxyConfig> clientProxyConfigs = ProxyServer.proxyMap.get(proxyConfig.getRemote());
                        Iterator<ClientProxyConfig> iterator = clientProxyConfigs.iterator();
                        while (iterator.hasNext()){
                            ClientProxyConfig next = iterator.next();
                            if (next.getClient().getClientId().equals(client.getClientId())){
                                iterator.remove();
                                break;
                            }
                        }
                        //判断是否这个转发端口已经没有代理客户端监听了
                        if (clientProxyConfigs.size() == 0){
                            ProxyServer.proxyMap.remove(proxyConfig.getRemote());
                            //关闭转发端口服务器
                            if (transmitServerMap.containsKey(proxyConfig.getRemote())){
                                transmitServerMap.get(proxyConfig.getRemote()).close();
                                transmitServerMap.remove(proxyConfig.getRemote());
                            }
                        }else{
                            ProxyServer.proxyMap.put(proxyConfig.getRemote(),clientProxyConfigs);
                        }
                    }

                }
                clientMaps.remove(client.getClientId());
            }
        }

        public void add(SocketClient client, List<ProxyConfig> proxyConfigs){
            for (ProxyConfig proxyConfig : proxyConfigs) {

                List<ClientProxyConfig> clientProxyConfigs = new ArrayList<>();
                if (ProxyServer.proxyMap.containsKey(proxyConfig.getRemote())){
                    clientProxyConfigs = ProxyServer.proxyMap.get(proxyConfig.getRemote());

//                String hostAddress1 = clientProxyConfigs.get(0).getClient().getSocket().getInetAddress().getHostAddress();
//                String hostAddress2 = client.getSocket().getInetAddress().getHostAddress();

                    Object token1 = clientProxyConfigs.get(0).getClient().getToken();
                    Object token2 = client.getToken();

                    //判断一下是不是一个用户
                    if (!token1.equals(token2)){

                        //发送配置错误给客户
                        try {
                            Message message = new Message();
                            message.setPort(proxyConfig.getPort());
                            message.setRemote(proxyConfig.getRemote());
                            message.setData("已被其他用户占用");

                            client.sendEventPack("proxyFail",message);
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }

                        continue;
                    }
                }


                //动态创建转发端口 且不是域名
                if (!transmitServerMap.containsKey(proxyConfig.getRemote()) && !proxyConfig.isDomain()){
                    TransmitServer transmitServer = null;
                    try {
                        transmitServer = new TransmitServer(Integer.parseInt(proxyConfig.getRemote()));
                        transmitServerMap.put(proxyConfig.getRemote(),transmitServer);
                    } catch (BindException e) {
//                    e.printStackTrace();

                        //发送配置错误给客户
                        try {
                            Message message = new Message();
                            message.setPort(proxyConfig.getPort());
                            message.setRemote(proxyConfig.getRemote());
                            message.setData(e.getMessage());

                            client.sendEventPack("proxyFail",message);
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }

                        continue;
                    }
                }

                ClientProxyConfig clientProxyConfig = new ClientProxyConfig();
                clientProxyConfig.setProxyConfig(proxyConfig);
                clientProxyConfig.setClient(client);
                clientProxyConfigs.add(clientProxyConfig);
                ProxyServer.proxyMap.put(proxyConfig.getRemote(),clientProxyConfigs);

            }
        }
    }
}
